package com.cedarhd.finance.msg.common.utils;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 网络请求类
 * @author Evan
 *
 */
public class HttpUtil {
	/**
	 * 创建 HttpClient
	 * 
	 * @param ssl true：创建HTTPS，false：创建HTTP
	 * @return
	 */
	private  static final Logger LOG = LoggerFactory.getLogger(HttpUtil.class);
	private static CloseableHttpClient buildHttpClient(boolean ssl) {
		CloseableHttpClient httpClient = null;
		
		if(ssl) {
			httpClient = buildHttpsClient();
		} else {
			httpClient = buildHttpClient();
		}
		
		return httpClient;
	}
	
	private static CloseableHttpClient buildHttpClient() {
		return HttpClients.createDefault();
	}
	
	private static CloseableHttpClient buildHttpsClient() {
		// 未实现
		return null;
	}
	
	/**
	 * 解析Http Response响应头
	 * 
	 * @param response
	 * @return
	 */
	private static Map<String, String> parseHeader(HttpResponse response) {
		Header[] headers = response.getAllHeaders();
		
		if(headers != null) {
			Map<String, String> map = new HashMap<String, String>(headers.length);
			
			for(Header header : headers) {
				map.put(header.getName(), header.getValue());
			}
			
			// 不包括Cookie
			map.remove("Set-Cookie");
			
			return map;
		}
		
		return null;
	}
	
	/**
	 * 解析Http Response响应Cookie
	 * 
	 * @param response
	 * @return
	 */
	private static Map<String, String> parseCookie(HttpResponse response) {
		Header[] cookies = response.getHeaders("Set-Cookie");
		
		if(cookies != null) {
			Map<String, String> map = new HashMap<String, String>(cookies.length);
			
			for(Header header : cookies) {
				String cookie = header.getValue().substring(0, header.getValue().indexOf(";"));
				String[] kv = cookie.split("=");
				
				if(kv.length == 2) {
					map.put(kv[0].trim(), kv[1].trim());
				} else {
					map.put(kv[0].trim(), "");
				}
			}
			
			return map;
		}
		
		return null;
	}
	
	/**
	 * 发起Http请求
	 * 
	 * @param request
	 * @param ssl 是否使用SSL
	 * @param respHeader 是否需要解析响应头
	 * @param respCookie 是否需要解析响应Cookie
	 * @return
	 * @throws Exception
	 */
	private static Map<String, Object> doRequest(HttpUriRequest request, boolean ssl, boolean respHeader, boolean respCookie) throws Exception {
		CloseableHttpClient httpClient = buildHttpClient(ssl);
		CloseableHttpResponse response = null;
		
		try {
			response = httpClient.execute(request);
			

				Map<String, Object> map = new HashMap<String, Object>();
					
				if(respHeader) {
					map.put("header", parseHeader(response));
				}
					
				if(respCookie) {
					map.put("cookie", parseCookie(response));
				}
					
				map.put("content", EntityUtils.toString(response.getEntity(), "UTF-8"));
					
				return map;

		}catch (Exception e){
			LOG.error("http error !",e);
		}finally {
			if(response != null) response.close();
			if(httpClient != null) httpClient.close();
		}
		
		return null;
	}
	
	/**
	 * 提交POST表单
	 * 
	 * @param url 接口地址
	 * @param form 表单参数
	 * @param headers 请求头
	 * @param respHeader 是否需要解析响应头
	 * @param respCookie 是否需要解析响应Cookie
	 * @return
	 */
	public static Map<String, Object> postHttpForm(String url, Map<String, String> form, Map<String, String> headers, boolean respHeader, boolean respCookie) {
		try {
			HttpPost httpPost = new HttpPost(url);
			
			if(form != null && !form.isEmpty()) {
				List<NameValuePair> params = new ArrayList <NameValuePair>();
				
				for(Entry<String, String> entry : form.entrySet()) {
					params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
				}
				
				httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
			}
			
			if(headers != null && !headers.isEmpty()) {
				for(Entry<String, String> entry : headers.entrySet()) {
					httpPost.addHeader(entry.getKey(), entry.getValue());
				}
			}
			
			return doRequest(httpPost, false, respHeader, respCookie);
		} catch(Exception e) {
			LOG.error("请求失败",e);
		}
		return null;
	}
	
	/**
	 * 提交POST表单
	 * 
	 * @param url 接口地址
	 * @param form 表单参数
	 * @param headers 请求头
	 * @return
	 */
	public static String postHttpForm(String url, Map<String, String> form, Map<String, String> headers) {
		Map<String, Object> response = postHttpForm(url, form, headers, false, false);
		
		if(response != null) {
			return String.valueOf(response.get("content"));
		}
		
		return null;
	}
	
	/**
	 * 提交POST Body
	 * 
	 * @param url 接口地址
	 * @param body 请求体
	 * @param headers 请求头
	 * @param respHeader
	 * @param respCookie
	 * @return
	 */
	public static Map<String, Object> postHttpBody(String url, String body, Map<String, String> headers, boolean respHeader, boolean respCookie) {
		try {
			HttpPost httpPost = new HttpPost(url);
			
			if(body != null) {
				httpPost.setEntity(new StringEntity(body, "UTF-8"));
			}
			
			if(headers != null && !headers.isEmpty()) {
				for(Entry<String, String> entry : headers.entrySet()) {
					httpPost.addHeader(entry.getKey(), entry.getValue());
				}
			}
			
			return doRequest(httpPost, false, respHeader, respCookie);
		} catch(Exception e) {
			LOG.error("请求失败",e);
		}
		return null;
	}
	
	/**
	 * 提交POST Body
	 * 
	 * @param url 接口地址
	 * @param body 请求体
	 * @param headers 请求头
	 * @return
	 */
	public static String postHttpBody(String url, String body, Map<String, String> headers) {
		Map<String, Object> response = postHttpBody(url, body, headers, false, false);
		
		if(response != null) {
			return String.valueOf(response.get("content"));
		}
		
		return null;
	}
	
	/**
	 * 提交GET请求
	 * 
	 * @param url 接口地址
	 * @param params 查询参数
	 * @param headers 请求头
	 * @param respHeader
	 * @param respCookie
	 * @return
	 */
	public static Map<String, Object> getHttp(String url, Map<String, String> params, Map<String, String> headers, boolean respHeader, boolean respCookie) {
		try {
			StringBuilder uri = new StringBuilder(url);
			
			if(params != null && !params.isEmpty()) {
				uri.append("?");
				
				for(Entry<String, String> entry : params.entrySet()) {
					uri.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
					uri.append("=");
					
					if(entry.getValue() != null) {
						uri.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
					}
					
					uri.append("&");
				}
			}
			
			HttpGet httpGet = new HttpGet(uri.toString());
			
			if(headers != null && !headers.isEmpty()) {
				for(Entry<String, String> entry : headers.entrySet()) {
					httpGet.addHeader(entry.getKey(), entry.getValue());
				}
			}
			
			return doRequest(httpGet, false, respHeader, respCookie);
		} catch(Exception e) {
			LOG.error("请求失败",e);
		}
		return null;
	}
	
	/**
	 * 提交GET请求
	 * 
	 * @param url 接口地址
	 * @param params 查询参数
	 * @param headers 请求头
	 * @return
	 */
	public static String getHttp(String url, Map<String, String> params, Map<String, String> headers) {
		Map<String, Object> response = getHttp(url, params, headers, false, false);
		
		if(response != null) {
			return String.valueOf(response.get("content"));
		}

		return null;
	}
}
